﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Web.UI.WebControls;
using System.Text;

namespace EWDTAssignment.App_Code
{
    public class BusinessLogic
    {
      
        //Simple Logic will be behind the code of the website
        /*Product
         * do not display items that contain QTY < 10
         * */

        
        #region Product Inventory Management
        /*ManageInventory
         * On Search Product ID, can only be integer
         * If textbox sProductID contain text and other field search for both item
         * */

        public static DataTable pmsSearchLogic(int pID, string productName, string type)
        {
            DataTable dt = new DataTable();

            if (pID > 0 && productName != "" && type != "")
            {//111
                dt = DBManager.searchProductByProductID_Name_Type(pID, productName, type);

            }
            if (pID > 0 && productName == "" && type == "")
            {//100
                dt = DBManager.searchProductByProductID(pID);

            }
            if (productName != "" && type != "" && pID == 0)
            {
                //011
                dt = DBManager.searchProductByProductName_Type(productName, type);
            }
            if (productName != "" && pID == 0 && type == "")
            {//010
                dt = DBManager.searchProductByProductName(productName);

            }
            if (type != "" && pID == 0 && productName == "")
            {//001
                dt = DBManager.searchProductByProductCat(type);

            }
            if (pID > 0 && productName != "" && type == "")
            {//110
                dt = DBManager.searchProductByProductID_Name(pID, productName);

            }
            if (pID > 0 && productName == "" && type != "")
            {//101
                dt = DBManager.searchProductByProductID_Name(pID, productName);

            }

            /*    if (pID > 0 && productName == "")
                    {

                    }
                if (pID > 0 && productName == "" && type == "")
                    {

                    }*/

            return dt;
        }


        public static Dictionary<string, string> productSpecDictionary()
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();


            //Mobo
            //spec changes




            dict.Add("cpu", "CPU Processor: ");

            dict.Add("enet", "Ethernet: ");
            dict.Add("audo", "Onboard audio: ");
            dict.Add("usbport", "USB port slot: ");
            dict.Add("additional", "Additional info ");
            //cpu
            dict.Add("freq", "Frequency ");
            dict.Add("cores", "Cores ");
            dict.Add("l2cache", "Level 2 Cache:");
            dict.Add("l3cache", "Level 3 Cache:");
            dict.Add("multi", "Multiplier:");
            dict.Add("uncore", "Uncore Speed:");
            dict.Add("voltlow", "Voltage low:");
            dict.Add("volthigh", "Voltage high:");
            //gfx

            dict.Add("gddrclass", "GDRAM Class:");

            dict.Add("mem", "Memory:");
            dict.Add("DX", "Direct X:");
            dict.Add("cpuclock", "CPU Clock:");
            dict.Add("memclock", "Memory Clock");
            //hdd
            dict.Add("storage", "Storage:");
            dict.Add("buffer", "Buffer Size(MB):");
            dict.Add("warranty", "Warranty:");


            return dict;
        }

        public static List<string> FormatSpecForProduct(string text)
        {
            List<string> test1 = new List<string>();
            string sb = text;
            string[] readline = sb.Split(',');

            string s1 = "";
            int rowcount = readline.Length;

            Dictionary<string, string> dict = App_Code.BusinessLogic.productSpecDictionary();
            for (int i = 0; i < rowcount; i++)
            {
                s1 = readline[i].ToString();
                string[] sub = s1.Split('=');
                if (dict.ContainsKey(sub[0]))
                {
                    s1 = s1.Replace(sub[0], dict[sub[0]]);
                    s1 = s1.Replace("=", " ");
                    test1.Add(s1);
                }

            }
            return test1;

        }

        public static List<string> FormatFlagForProduct(string text)
        {
            List<string> test1 = new List<string>();
            string sb = text;
            string[] readline = sb.Split(',');

            string s1 = "";
            int rowcount = readline.Length;

            for (int i = 0; i < rowcount; i++)
            {
                s1 = readline[i].ToString();
                string[] sub = s1.Split('=');

                s1 = s1.Replace("=", " ");
                test1.Add(s1);
            }


            return test1;

        }


        #endregion

        #region Timothy
        #region Product Flag/Specfication Logic

        public static Dictionary<string, string> DelimitCSV(string fs)
        {
            Dictionary<string, string> d = new Dictionary<string, string>();

            if (fs != null)
            {
                foreach (string s in fs.Split(','))
                {
                    string[] sub = s.Split('=');
                    d.Add(sub[0], sub[1]);
                }
            }
            return d;
        }

        public static int range(int type, int mod)
        {
            int i = type + mod;

            if (i < 1 || i > 5)
            {
                i = type;
            }
            return i;
        }

        #endregion

        #region Sets logic

        //Retrieves and displays info of products within a set
        public static void GenerateSetList(int setID, List<Label> lblList, params Label[] Error)
        {
            if (setID > 0)
            {
                List<Products> pList = EntityLogic.RetrieveSetContents(setID);

                foreach (Label l in lblList)
                {
                    l.Text = "";
                    l.ForeColor = System.Drawing.Color.Black;
                }

                if (pList.Count != 0)
                {
                    lblList[0].Text = "Set #" + setID.ToString();

                    int HDDTotal = 0, hddcount = 1;
                    StringBuilder sb = new StringBuilder();
                    string hdds = "";

                    foreach (Products p in pList)
                    {
                        Dictionary<string, string> pFlag = BusinessLogic.DelimitCSV(p.Flag);
                        Dictionary<string, string> pSpec = BusinessLogic.DelimitCSV(p.Specification);

                        #region Label switch case
                        switch (p.Category)
                        {
                            case "Motherboard":
                                sb.Append("Socket: " + pFlag["socket"] + " (" + pSpec["cpu"] + ")")
                                    .Append("<br>RAM Slots: " + pFlag["ramN"] + " x " + pFlag["ram"])
                                    .Append("<br>RAM Speeds Supported: ");

                                if (Convert.ToInt32(pSpec["rss2000"]) == 1)
                                {
                                    sb.Append("2000/");
                                }

                                if (Convert.ToInt32(pSpec["rss1866"]) == 1)
                                {
                                    sb.Append("1866/");
                                }

                                if (Convert.ToInt32(pSpec["rss1800"]) == 1)
                                {
                                    sb.Append("1800/");
                                }

                                if (Convert.ToInt32(pSpec["rss1600"]) == 1)
                                {
                                    sb.Append("1600/");
                                }

                                if (Convert.ToInt32(pSpec["rss1333"]) == 1)
                                {
                                    sb.Append("1333/");
                                }

                                if (Convert.ToInt32(pSpec["rss1066"]) == 1)
                                {
                                    sb.Append("1066/");
                                }

                                lblList[1].Text = sb.ToString();
                                sb.Clear();

                                break;

                            case "CPU":

                                sb.Append("Frequency: ");
                                if (Convert.ToInt32(pSpec["freq"]) > 999)
                                {
                                    double d = Convert.ToInt32(pSpec["freq"]) / 1000;
                                    sb.Append(d.ToString() + " GHz<br>");
                                }
                                else
                                {
                                    sb.Append(Convert.ToInt32(pSpec["freq"]) + "MHz<br>");
                                }
                                sb.Append("Socket: " + pFlag["socket"]);

                                lblList[2].Text = sb.ToString();
                                sb.Clear();

                                break;

                            case "RAM":

                                sb.Append("Class: " + pFlag["class"]);
                                sb.Append(" " + pFlag["slot"] + " x " + pFlag["mem"] + "GB");

                                if (pSpec.ContainsKey("freq"))
                                {
                                    sb.Append("<br>Frequency: " + pSpec["freq"] + "MHz");
                                }

                                if (pFlag.ContainsKey("dram"))
                                {
                                    sb.Append("<br>DRAM: " + pSpec["timing"]);
                                }

                                lblList[3].Text = sb.ToString();
                                sb.Clear();
                                break;

                            case "GFX":

                                int q = EntityLogic.RetrieveSetItemQuantity(p, setID);

                                sb.Append("Graphic RAM: GDDR" + pSpec["gddrclass"] + " x " + pSpec["mem"])
                                    .Append("<br>Supports DirectX: DX" + pSpec["DX"])
                                    .Append("<br>Default CPU/Memory Clock: " + pSpec["cpuclock"] + " / " + pSpec["memclock"]);

                                if (pFlag.ContainsKey("SLI"))
                                {
                                    if (pFlag["SLI"] == "1")
                                    {
                                        sb.Append("<br>SLI: Yes");
                                        if (q == 2)
                                        {
                                            sb.Append("<br>In SLI Mode");
                                        }
                                    }
                                }
                                if (pFlag.ContainsKey("CrossFireX"))
                                {
                                    if (pFlag["CrossFireX"] == "1")
                                    {
                                        if (q == 2)
                                        {
                                            sb.Append("<br>CrossFireX: Yes");
                                            sb.Append("<br>In CrossFireX Mode");
                                        }
                                    }
                                }


                                lblList[4].Text = sb.ToString();
                                sb.Clear();
                                break;

                            case "HDD":

                                int storage = Convert.ToInt32(pSpec["storage"]), quantity = EntityLogic.RetrieveSetItemQuantity(p, setID);
                                if (storage > 0)
                                {
                                    for (int i = 0; i < quantity; i++)
                                    {
                                        sb.Append("HDD #" + hddcount + ": " + pFlag["type"] + "/" + pSpec["buffer"] + " ");

                                        if (storage > 999)
                                        {
                                            double d = Convert.ToDouble(pSpec["storage"]) / 1000;
                                            sb.Append(d.ToString() + " TB");
                                        }
                                        else
                                        {
                                            sb.Append(storage + "GB");
                                        }
                                        sb.Append("<br>");
                                        hddcount++;
                                    }
                                    HDDTotal += (storage * Convert.ToInt32(quantity));
                                }

                                hdds += sb.ToString();
                                sb.Clear();
                                break;

                            case "Soundcard":
                                sb.Append("Surround Sound: " + pSpec["surround"]);
                                lblList[6].Text = sb.ToString();
                                sb.Clear();

                                break;

                            case "PSU":
                                sb.Append("Capacity: " + pFlag["capacity"] + "W");
                                lblList[7].Text = sb.ToString();
                                sb.Clear();
                                break;

                            case "Casing":
                                sb.Append("Form factor: " + pFlag["form"]);
                                lblList[8].Text = sb.ToString();
                                sb.Clear();
                                break;
                        }


                        #endregion

                    }
                    if (HDDTotal > 999)
                    {
                        double d = Convert.ToDouble(HDDTotal) / 1000;
                        sb.Append(d.ToString() + " TB");
                    }
                    else
                    {
                        sb.Append(HDDTotal + "GB");
                    }
                    lblList[5].Text = hdds + "Total Storage: " + sb.ToString();

                    foreach (Label l in lblList)
                    {
                        l.Visible = true;
                    }
                }
                else
                {
                    foreach (Label l in lblList)
                    {
                        l.Text = "";
                        l.Visible = false;
                        Error[0].Text = "Set ID#" + setID + " not found.";
                    }
                }
            }
            else
            {
                foreach (Label l in lblList)
                {
                    l.Text = "";
                    l.Visible = false;
                }
            }
        }

        //Checks for repeated values in a list and return a Dictionary with <ProductID : Instances of the productID>
        public static Dictionary<int, int> SetItemQuantityChk(List<int> itemList)
        {
            Dictionary<int, int> quantity = new Dictionary<int, int>();

            foreach (int i in itemList)
            {
                if (!quantity.ContainsKey(i))
                {
                    quantity.Add(i, 1);
                }
                else
                {
                    quantity[i]++;
                }
            }
            return quantity;
        }

        public static Dictionary<int, int> CompareSetChanges(List<int> oldList, List<int> newList)
        {
            Dictionary<int, int> d1 = new Dictionary<int, int>();
            Dictionary<int, int> d2 = SetItemQuantityChk(oldList);
            Dictionary<int, int> d3 = SetItemQuantityChk(newList);

            int count = d2.Count();

            foreach (KeyValuePair<int, int> kvp in d2)
            {
                int key = kvp.Key, val = kvp.Value;

                if (d3.ContainsKey(kvp.Key))
                {
                    if (!(d3[kvp.Key] == val))
                    {
                        val = d3[kvp.Key];
                    }
                    d1.Add(key, val);
                }
                else
                {
                    d1.Add(kvp.Key, 0);
                }

            }

            foreach (KeyValuePair<int, int> kvp in d3)
            {
                if (!d1.ContainsKey(kvp.Key))
                {
                    d1.Add(kvp.Key, kvp.Value);
                }
            }
            return d1;
        }

        public static void UpdateSet(List<int> oldList, List<int> newList, int setID)
        {
            Dictionary<int, int> d = BusinessLogic.CompareSetChanges(oldList, newList);

            int origAccID = EntityLogic.RetrieveSetItemAccID(setID);

            foreach (KeyValuePair<int, int> kvp in d)
            {
                if (kvp.Key != 0)
                {
                    EntityLogic.UpdateSetItemTuple(setID, kvp.Key, kvp.Value, origAccID);
                }
            }
        }

        public static void populateSetList(DropDownList ddl, int accID)
        {
            List<int> sList = EntityLogic.RetrieveSetList(Convert.ToInt32(accID));

            ListItem li = new ListItem("[Select One]", "0");
            ddl.Items.Add(li);
            foreach (int s in sList)
            {
                li = new ListItem("Set #" + s.ToString(), s.ToString());
                ddl.Items.Add(li);
            }
        }


        #endregion

        #region  Comparison logic

        public static void CompareSets(List<Label> lbl1, List<Label> lbl2, List<int> setID)
        {
            List<Products> p1 = EntityLogic.RetrieveSetContents(setID[0]);
            List<Products> p2 = EntityLogic.RetrieveSetContents(setID[1]);

            Dictionary<string, int> score1 = ScoreCheck(p1, setID[0]);
            Dictionary<string, int> score2 = ScoreCheck(p2, setID[1]);

            foreach (KeyValuePair<string, int> kvp in score1)
            {
                switch (kvp.Key)
                {
                    case "Motherboard":
                        CompareScore(Convert.ToInt32(score1[kvp.Key]), Convert.ToInt32(score2[kvp.Key]), lbl1[1], lbl2[1]);
                        break;
                    case "CPU":
                        CompareScore(Convert.ToInt32(score1[kvp.Key]), Convert.ToInt32(score2[kvp.Key]), lbl1[2], lbl2[2]);
                        break;
                    case "RAM":
                        CompareScore(Convert.ToInt32(score1[kvp.Key]), Convert.ToInt32(score2[kvp.Key]), lbl1[3], lbl2[3]);
                        break;
                    case "GFX":
                        CompareScore(Convert.ToInt32(score1[kvp.Key]), Convert.ToInt32(score2[kvp.Key]), lbl1[4], lbl2[4]);
                        break;
                    case "HDD":
                        CompareScore(Convert.ToInt32(score1[kvp.Key]), Convert.ToInt32(score2[kvp.Key]), lbl1[5], lbl2[5]);
                        break;
                    case "Soundcard":
                        CompareScore(Convert.ToInt32(score1[kvp.Key]), Convert.ToInt32(score2[kvp.Key]), lbl1[6], lbl2[6]);
                        break;
                    case "PSU":
                        CompareScore(Convert.ToInt32(score1[kvp.Key]), Convert.ToInt32(score2[kvp.Key]), lbl1[7], lbl2[7]);
                        break;
                    case "Casing":
                        CompareScore(Convert.ToInt32(score1[kvp.Key]), Convert.ToInt32(score2[kvp.Key]), lbl1[8], lbl2[8]);
                        break;
                }
                
            }
        }

        public static Dictionary<string, int> ScoreCheck(List<Products> pList, int setID)
        {
            Dictionary<string, int> score = new Dictionary<string, int>();
            score.Add("Motherboard", 0);
            score.Add("CPU", 0);
            score.Add("RAM", 0);
            score.Add("GFX", 0);
            score.Add("HDD", 0);
            score.Add("Soundcard", 0);
            score.Add("PSU", 0);
            score.Add("Casing", 0);

            //Simplified logic for scores
            foreach (Products p in pList)
            {
                Dictionary<string, string> pFlag = BusinessLogic.DelimitCSV(p.Flag);
                Dictionary<string, string> pSpec = BusinessLogic.DelimitCSV(p.Specification);
                int marks = 0;
                switch (p.Category)
                {
                    case "Motherboard":
                        switch (pSpec["cpu"])
                        {
                            case "i7":
                                marks = 7;
                                break;
                            case "i5":
                                marks = 5;
                                break;
                            case "i3":
                                marks = 3;
                                break;
                            case "C2D":
                                marks = 1;
                                break;
                            case "C2Q":
                                marks = 2;
                                break;
                            default:
                                marks = 0;
                                break;
                        }

                        int rammarks = 0;
                        if (Convert.ToInt32(pSpec["rss2000"]) == 1)
                        {
                            rammarks += 1;
                        }
                        if (Convert.ToInt32(pSpec["rss1866"]) == 1)
                        {
                            rammarks += 1;
                        }
                        if (Convert.ToInt32(pSpec["rss1800"]) == 1)
                        {
                            rammarks += 1;
                        }
                        if (Convert.ToInt32(pSpec["rss1600"]) == 1)
                        {
                            rammarks += 1;
                        }
                        if (Convert.ToInt32(pSpec["rss1333"]) == 1)
                        {
                            rammarks += 1;
                        }
                        if (Convert.ToInt32(pSpec["rss1066"]) == 1)
                        {
                            rammarks += 1;
                        }
                        marks *= rammarks;

                        marks += Convert.ToInt32(pFlag["hddN"]);


                        break;
                    case "CPU":
                        marks = Convert.ToInt32(pSpec["freq"]) * Convert.ToInt32(pSpec["cores"]);
                        break;
                    case "RAM":
                        marks = Convert.ToInt32(pFlag["class"].Replace("DDR", "")) * Convert.ToInt32(pFlag["mem"]) * Convert.ToInt32(pFlag["slot"]);
                        break;
                    case "GFX":
                        marks = Convert.ToInt32(pSpec["mem"].Replace("GB", "")) * Convert.ToInt32(pSpec["cpuclock"]) * Convert.ToInt32(pSpec["memclock"]);
                        if (pFlag.ContainsKey("SLI"))
                        {
                            if (Convert.ToInt32(pFlag["SLI"]) == 1)
                            {
                                if (EntityLogic.RetrieveSetItemQuantity(p, setID) ==2 )
                                {
                                    marks *= 3;
                                }
                            }
                        }
                        if (pFlag.ContainsKey("CrossFireX"))
                        {
                            if (Convert.ToInt32(pFlag["CrossFireX"]) == 1)
                            {
                                if (EntityLogic.RetrieveSetItemQuantity(p, setID) == 2)
                                {
                                    marks *= 3;
                                }
                            }
                        }
                        break;
                    case "HDD":
                        marks = Convert.ToInt32(pFlag["type"].Replace("SATA","")) * Convert.ToInt32(pSpec["storage"]) * Convert.ToInt32(pSpec["buffer"]);
                        break;
                    case "Soundcard":
                        marks = (int) Convert.ToDouble(pSpec["surround"]) * 10;
                        break;
                    case "PSU":
                        marks = Convert.ToInt32(pFlag["capacity"]);
                        break;
                    case "Casing":
                        marks = 1;
                        break;
                }
                score[p.Category] = marks;
            }

            return score;
        }

        public static void CompareScore(int val1, int val2, Label lbl1, Label lbl2)
        {
            if (val1 > val2)
            {
                lbl1.ForeColor = System.Drawing.Color.Green;
                lbl2.ForeColor = System.Drawing.Color.Red;
            }
            else
            {
                if (val1 < val2)
                {
                    lbl1.ForeColor = System.Drawing.Color.Red;
                    lbl2.ForeColor = System.Drawing.Color.Green;
                }
                else
                {
                    lbl1.ForeColor = System.Drawing.Color.Gray;
                    lbl2.ForeColor = System.Drawing.Color.Gray;
                }
            }
        }
        #endregion

        #region Misc
        public static List<Label> CreateLabelList(params Label[] lbl)
        {
            List<Label> lblList = new List<Label>();

            foreach (Label l in lbl)
            {
                lblList.Add(l);
            }

            return lblList;
        }
        #endregion
        #endregion

    }
}
